package cn.toutatis.common.result;

import cn.toutatis.common.config.ResultCode;
import cn.toutatis.common.config.TimeConstant;
import com.fasterxml.jackson.annotation.JsonIgnore;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * @author Toutatis_Gc
 */
public class Result implements Serializable {

    @JsonIgnore
    private boolean autoConfig = false;

    public Result(){ }

    public Result(boolean autoConfig) {
        this.autoConfig = autoConfig;
    }

    @JsonIgnore
    private Actions actions;

    private boolean alreadyAutoSetSign = false;

    private Boolean originalSign = null;

    private boolean sign = false;

    private String code = "";

    private String message = "";

    private Object otherMsg = "";

    private long timestamp = System.currentTimeMillis();

    private String resultTime = TimeConstant.INSTANCE.getCurrentTimeByLong(timestamp);

    private Object content = null;

    public boolean isSign() {
        return sign;
    }

    public void setSign(boolean sign,Actions action) {
        this.actions = action;
        setSign(sign);
        if (this.autoConfig){
            if (!alreadyAutoSetSign){
                if (actions!= null){
                    switch (actions){
                        case SELECT:
                            checkAutoSign(ResultCode.NORMAL_SUCCESS,ResultCode.NORMAL_SUCCESS_BUT_NULL);
                            break;
                        case UPDATE:
                            checkAutoSign(ResultCode.UPDATE_SUCCESS,ResultCode.UPDATE_FAILED);
                            break;
                        case CHECKED:
                            checkAutoSign(ResultCode.APPLY_SUCCESS,ResultCode.APPLY_FAILED);
                            break;
                        case INSERT:
                            checkAutoSign(ResultCode.INSERT_SUCCESS,ResultCode.INSERT_FAILED);
                            break;
                        case DELETE:
                            checkAutoSign(ResultCode.DELETE_SUCCESS,ResultCode.DELETE_FAILED);
                            break;
                        default:
                            break;
                    }
                }else {
                    updateEnv(ResultCode.NORMAL_SUCCESS);
                }
                alreadyAutoSetSign = true;
            }
        }
    }

    public void setSign(boolean sign) {
        this.sign = sign;
        this.originalSign = sign;
    }

    public void setAutoConfig(boolean autoConfig) {
        this.autoConfig = autoConfig;
    }

    public Actions getActions() {
        return actions;
    }

    public void setActions(Actions actions) {
        this.actions = actions;
    }

    public Object getOtherMsg() {
        return otherMsg;
    }

    public void setOtherMsg(Object otherMsg) {
        this.otherMsg = otherMsg;
    }

    public String getCode() {
        return code;
    }

    public void setCode(ResultCode code) {
        this.code = code.getCode();
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(ResultCode resultCode) {
        this.message = resultCode.getInfo();
    }


    public long getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }

    public String getResultTime() {
        return resultTime;
    }

    public void setResultTime(String resultTime) {
        this.resultTime = resultTime;
    }

    public Object getContent() {
        return content;
    }

    public void setContent(Object content,Actions action){
        this.actions = action;
        setContent(content);
    }

    public void setContent(Object content) {
        this.content = content;
        if (this.autoConfig){
            if (!alreadyAutoSetSign){
                if (actions!= null){
                    checkContent(actions);
                }else {
//                无任何标记默认为普通请求
                    updateEnv(ResultCode.NORMAL_SUCCESS);
                }
            }
        }
    }

    private static final String LIST = "LIST";
    private static final String MAP = "MAP";
    private static final String OBJECT = "OBJECT";
    private static final String UNKNOWN = "UNKNOWN";

    private void checkContent(Actions action){
         String classify = UNKNOWN;
        boolean notEmpty = false;
        if (content != null){
            Class<?> contentClass = content.getClass();
            if (List.class.isAssignableFrom(contentClass)){
                List lengthSize = (List) content;
                this.sign = notEmpty = lengthSize.size() > 0;
                classify = LIST;
            }else if (Map.class.isAssignableFrom(contentClass)){
                Map mapSize = (Map) content;
                this.sign = notEmpty = !mapSize.isEmpty();
                classify = MAP;
            }else if (Object.class.isAssignableFrom(contentClass)){
                this.sign = notEmpty = content!= null;
                classify = OBJECT;
            }else {
                this.sign = notEmpty = false;
                classify = UNKNOWN;
            }
        }
//        获取动作,如果是更新等操作,获取的为sign的标志,查询为自动设置的content内容是否为空
        if (!UNKNOWN.equals(classify)){
            switch (action){
                case SELECT:
                    updateEnv(notEmpty,ResultCode.NORMAL_SUCCESS,ResultCode.NORMAL_SUCCESS_BUT_NULL);
                    break;
                case UPDATE:
                    checkAutoSign(ResultCode.UPDATE_SUCCESS,ResultCode.UPDATE_FAILED);
                    break;
                case CHECKED:
                    checkAutoSign(ResultCode.APPLY_SUCCESS,ResultCode.APPLY_FAILED);
                    break;
                case INSERT:
                    checkAutoSign(ResultCode.INSERT_SUCCESS,ResultCode.INSERT_FAILED);
                    break;
                case DELETE:
                    checkAutoSign(ResultCode.DELETE_SUCCESS,ResultCode.DELETE_FAILED);
                    break;
                default:
                    break;
            }
        }else {
            updateEnv(ResultCode.NULL_DIRECT_CODE);
        }
//       总感觉这里漏掉了什么东西
        if (originalSign != null){
            this.sign = originalSign;
            updateEnv(originalSign,ResultCode.NORMAL_SUCCESS,ResultCode.NORMAL_FAILED);
        }else if (action == null){
            updateEnv(this.sign,ResultCode.NORMAL_SUCCESS,ResultCode.NORMAL_FAILED);
        }
        alreadyAutoSetSign = true;
    }

    private void checkAutoSign(ResultCode successCode,ResultCode failCode){
        if (originalSign == null){
            if (this.sign){
                updateEnv(successCode);
            } else {
                updateEnv(failCode);
            }
        }else {
            if (originalSign){
                updateEnv(successCode);
            } else {
                updateEnv(failCode);
            }
        }
    }

    private void updateEnv(boolean b,ResultCode success,ResultCode failCode){
        if (b){
            updateEnv(success);
        }else {
            updateEnv(failCode);
        }
    }

    private void updateEnv(ResultCode code){
        this.setCode(code);
        this.setMessage(code);
    }

    @Override
    public String toString() {
        return "Result{" +
                "autoConfig=" + autoConfig +
                ", actions=" + actions +
                ", alreadyAutoSetSign=" + alreadyAutoSetSign +
                ", originalSign=" + originalSign +
                ", sign=" + sign +
                ", code='" + code + '\'' +
                ", message='" + message + '\'' +
                ", otherMsg=" + otherMsg +
                ", timestamp=" + timestamp +
                ", resultTime='" + resultTime + '\'' +
                ", content=" + content +
                '}';
    }
}
